package com.ncmmall.api.apis.mall;


import com.ncmmall.api.apis.service.Result;
import com.ncmmall.api.params.MerchantShoppingCartGoodsDTO;
import com.ncmmall.api.params.ShopCartDTO;
import com.ncmmall.api.security.Securitys;
import com.ncmmall.application.business.shoppingcart.ShoppingCartApplication;
import com.feijin.commons.exceptions.InterfaceException;
import com.feijin.commons.lang.ArithUtils;
import com.ncmmall.domain.business.goods.sku.GoodsSku;
import com.ncmmall.domain.business.goods.sku.QGoodsSku;
import com.ncmmall.domain.business.goods.unit.GoodsUnit;
import com.ncmmall.domain.business.goods.unit.QGoodsUnit;
import com.ncmmall.domain.business.shoppingcart.QShoppingCart;
import com.ncmmall.domain.business.shoppingcart.ShoppingCart;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author linxs
 * 购物车
 */
@RestController
@RequestMapping(value = "/shoppingcart")
@Component
public class ShoppingCartApi {

    private final Logger logger = LoggerFactory.getLogger(ShoppingCartApi.class);

    @Autowired
    private QueryChannelService queryChannelService;

    @Autowired
    private ShoppingCartApplication shoppingCartApplication;

    @Value("${store.domain}")
    private String storeDomain;

    /**
     * 购物车商品数量
     */
    @RequestMapping(value = "/count", method = RequestMethod.GET)
    @ResponseBody
    public Result count(HttpServletRequest request) {
        Result result = new Result();
        try {

            WebUser member = Securitys.user(request);
            List<ShoppingCart> carts = queryChannelService.findAll(QShoppingCart.shoppingCart.member.eq(member), ShoppingCart.class);
            return result.ok().inject(ImmutableMap.of("count", carts.size()));

        } catch (Exception e) {
            logger.error("[获取购物车商品数量异常]", e);
            return result.fail().setMsg("网络连接失败");
        }

    }

    /**
     * 添加商品到购物车
     */
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public Result add(HttpServletRequest request, @RequestBody List<ShopCartDTO> paramses) {
        Result result = new Result();

        try {

            WebUser member = Securitys.user(request);

            List<GoodsSku> skus = Lists.newArrayList();
            List<Integer> quantitys = Lists.newArrayList();
            List<Integer> unitQuantitys = Lists.newArrayList();
            List<GoodsUnit> units = Lists.newArrayList();

            for (ShopCartDTO paramse : paramses) {
                GoodsSku sku = queryChannelService.findOne(QGoodsSku.goodsSku.id.eq(paramse.getId()), GoodsSku.class);
                GoodsUnit unit = queryChannelService.findOne(QGoodsUnit.goodsUnit.id.eq(paramse.getUnitId()), GoodsUnit.class);

                units.add(unit);
                skus.add(sku);
                quantitys.add(paramse.getQuantity());
                unitQuantitys.add(paramse.getUnitQuantity());
            }

            shoppingCartApplication.addGoodsToShoppingCartOfSupplier(member, skus, units, quantitys, unitQuantitys);

            return result.ok();

        } catch (Exception e) {

            if (e instanceof InterfaceException) {
                return result.fail().setMsg(e.getMessage());
            }

            logger.error("[添加购物车异常]", e);
            return result.fail().setMsg("添加商品到购物车失败");
        }

    }


    /**
     * 修改商品在购物车中的数量
     */
    @RequestMapping(value = "/modify", method = RequestMethod.PUT)
    @ResponseBody
    public Result modify(HttpServletRequest request, @RequestBody ShopCartDTO params) {
        Result result = new Result();

        try {

            QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
            WebUser member = Securitys.user(request);
            ShoppingCart cart = queryChannelService.findOne(qShoppingCart.member.eq(member).and(qShoppingCart.id.eq(params.getId())), ShoppingCart.class);
            GoodsUnit unit = queryChannelService.findOne(QGoodsUnit.goodsUnit.id.eq(params.getUnitId()), GoodsUnit.class);

            shoppingCartApplication.modifySupplierQuantity(cart, params.getQuantity(), unit, params.getUnitQuantity());

            return result.ok();

        } catch (Exception e) {

            if (e instanceof InterfaceException) {
                return result.fail().setMsg(e.getMessage());
            }

            logger.error("[修改购物车商品数据异常]", e);
            return result.fail().setMsg("修改数量失败");
        }

    }

    /**
     * 批量删除购物车内的商品
     */
    @RequestMapping(value = "/removes", method = RequestMethod.DELETE)
    @ResponseBody
    public Result removes(HttpServletRequest request, @RequestBody List<ShopCartDTO> params) {
        Result result = new Result();

        try {

            QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
            WebUser member = Securitys.user(request);
            List<ShoppingCart> carts = queryChannelService.findAll(qShoppingCart.member.eq(member).and(qShoppingCart.id.in(Lists.transform(params, new Function<ShopCartDTO, Long>() {
                @Nullable
                @Override
                public Long apply(@Nullable ShopCartDTO input) {
                    return input.getId();
                }
            }))), ShoppingCart.class);

            shoppingCartApplication.removes(carts);

            return result.ok();

        } catch (Exception e) {
            logger.error("[批量删除购物车内商品异常]", e);
            return result.fail().setMsg("添加商品到购物车失败");
        }

    }

    /**
     * 购物车商品列表
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ResponseBody
    public Result list(HttpServletRequest request) {
        Result result = new Result();
        try {

            WebUser member = Securitys.user(request);

            List<ShoppingCart> loseGoodsList = Lists.newArrayList();

            //获取去重后的商家ID
            List<Long> merchantIds = Lists.newArrayList();
            List<ShoppingCart> shoppingCarts = queryChannelService.findAll(QShoppingCart.shoppingCart.member.eq(member), ShoppingCart.class);
            for (ShoppingCart cart : shoppingCarts) {
                if (!merchantIds.contains(cart.getSku().getGoods().getMerchant().getId())) {
                    merchantIds.add(cart.getSku().getMerchant().getId());
                }
                cart.setUnitQuantity(cart.getQuantity());
            }

            List<WebUser> merchants = merchantIds.stream().map(input -> queryChannelService.findOne(QWebUser.webUser.id.eq(input), WebUser.class)).collect(Collectors.toList());

            List<MerchantShoppingCartGoodsDTO> shopCartListDTOs = Lists.newArrayList();
            for (WebUser merchant : merchants) {
                MerchantShoppingCartGoodsDTO merchantItem = new MerchantShoppingCartGoodsDTO();
                merchantItem.setMerchantId(merchant.getId());
                merchantItem.setMerchantName(merchant.getShopName());

                List<ShoppingCart> items = Lists.newArrayList();

                double subtotalPrice = 0;

                for (ShoppingCart cart : shoppingCarts) {

                    if (cart.getSku().getGoods().getMerchant().getId() == merchant.getId()) {
                        cart.setGoodsImage(storeDomain + "/uploads/" + cart.getGoodsImage());
                        cart.setGoodsId(cart.getSku().getGoods().getId());
                        cart.setGoodsStatus(cart.getSku().getGoods().getStatus());

                        cart.setGoodsUnit(cart.getSku().getGoods().getUnit());
                        cart.setAffiliatedUnit(cart.getSku().getGoods().getAffiliatedUnit());
                        cart.setAffiliatedUnitValue(cart.getSku().getGoods().getAffiliatedUnitValue());
                        cart.setUltimateUnit(cart.getSku().getGoods().getUltimateUnit());
                        cart.setUltimateUnitValue(cart.getSku().getGoods().getUltimateUnitValue());

                        if (cart.getGoodsUnit().getId() == cart.getUnit().getId()) {
                            cart.setUnitValue(1);
                        } else if (cart.getAffiliatedUnit() != null && cart.getAffiliatedUnit().getId() == cart.getUnit().getId()) {
                            cart.setUnitValue(cart.getAffiliatedUnitValue());
                        } else if (cart.getUltimateUnit() != null && cart.getUltimateUnit().getId() == cart.getUnit().getId()) {
                            cart.setUnitValue(cart.getUltimateUnitValue());
                        }

                        subtotalPrice = ArithUtils.add(subtotalPrice, cart.getSubtotalPrice());

                        items.add(cart);

                        if (cart.getGoodsStatus() != 3) {
                            loseGoodsList.add(cart);
                        }

                    }

                }

                merchantItem.setGoodsList(items);
                merchantItem.setSubtotalPrice(subtotalPrice);
                shopCartListDTOs.add(merchantItem);

            }

            return result.ok().inject(ImmutableMap.of("merchants", shopCartListDTOs, "loseGoodsList", loseGoodsList));

        } catch (Exception e) {
            logger.error("[购物车商品列表异常]", e);
            return result.fail().setMsg("网络连接失败");
        }

    }


}
